package edu.tsinghua.oxy.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * 处理URL的工具
 *
 * @author sean
 * @date 2021 - 07 - 29 下午2:27
 */
@Slf4j
@Component
public class UrlUtils {

    /**
     * 顶级域名，用"|"分割
     * 如果有处理的网站的顶级域名不在列表中，可以在配置文件中添加
     */
    @Value("${spider.website.domain.top}")
    String topDomain;

    private Set<String> suffixSet;

    private final static Pattern IP_PATTERN = Pattern.compile("(\\d{1,3}\\.){3}(\\d{1,3})");

    /**
     * 判断URL的顶级域名是否在配置的列表中
     * @param suffix
     * @return
     */
    private boolean containedTopDomain(String suffix){
        synchronized (this) {
            suffixSet = CollectionUtils.isEmpty(suffixSet) ? new HashSet<>(Arrays.asList(topDomain.split("\\|"))) : suffixSet;
        }
        return suffixSet.contains(suffix);
    }

    /**
     * 获取url的域名
     *
     * @param url
     * @return
     */
    public String getDomainName(URL url) {
        // 将host转为小写
        String host = url.getHost().toLowerCase();
        String separate = ".";
        if (host.endsWith(separate)) {
            // 去掉末尾的"."号
            host = host.substring(0, host.length() - 1);
        }

        // 正则匹配
        if (IP_PATTERN.matcher(host).matches()) {
            return host;
        }

        int index = 0;
        String candidate = host;
        for (; index >= 0; ) {
            /**
             * 逐层去掉低级域名，直到下一级为顶级域名，返回当前域名
             */
            index = candidate.indexOf('.');
            String subCandidate = candidate.substring(index + 1);
            if (containedTopDomain(subCandidate)) {
                return candidate;
            }
            candidate = subCandidate;
        }
        return candidate;
    }

    /**
     * 获取url的域名
     *
     * @param url
     * @return
     * @throws MalformedURLException
     */
    public String getDomainName(String url) throws MalformedURLException {
        return getDomainName(new URL(url));
    }

    /**
     * 判断两个url顶级域名是否相等
     *
     * @param url1
     * @param url2
     * @return
     */
    public boolean isSameDomainName(URL url1, URL url2) {
        return getDomainName(url1).equalsIgnoreCase(getDomainName(url2));
    }

    /**
     * 判断两个url顶级域名是否相等
     *
     * @param url1
     * @param url2
     * @return
     * @throws MalformedURLException
     */
    public boolean isSameDomainName(String url1, String url2)
            throws MalformedURLException {
        return isSameDomainName(new URL(url1), new URL(url2));
    }

    public static void main(String[] args) throws Exception {
        String urlStr = "http://news.heXun.com/2017-09-23/190978248.html";
//        urlStr = "http://127.0.0.1:8080/2017-09-23/190978248.html";
        urlStr = "https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4?start=0&type=T";
        UrlUtils urlUtils = new UrlUtils();
        log.info(urlUtils.getDomainName(urlStr));
        urlUtils.getDomainName(new URL(urlStr));
    }

}

